<template>
  <el-button-group style="margin: 0 12px">
    <el-button v-bind="$attrs" type="primary" plain @click="open"
      >{{ t('conditionTree.openBtn') }}
      <el-icon class="el-icon--right">
        <Filter />
      </el-icon>
    </el-button>
    <el-button type="primary" plain :disabled="!advanced" @click="resetAdvance">
      {{ t('common.cancel') }}
      <Icon icon="ep:refresh" class="ml-5px" />
    </el-button>
  </el-button-group>

  <el-drawer
    v-model="drawer"
    :title="t('conditionTree.openBtn')"
    :size="mobile ? '100%' : '750'"
    :append-to-body="true"
    destroy-on-close
  >
    <el-button
      v-if="condition.conditions?.length === 0"
      type="primary"
      text
      @click="addNewCondition"
    >
      <el-icon class="el-icon--left">
        <Plus />
      </el-icon>
      {{ t('conditionTree.addCondition') }}
    </el-button>

    <ConditionGroup ref="conditionRef" :id="condition.id" :schemata="schemata" />

    <template #footer>
      <el-button
        type="primary"
        @click="advanceSearch"
        :disabled="condition.conditions?.length === 0"
        >{{ t('conditionTree.search') }}
      </el-button>
      <el-popconfirm :title="t('conditionTree.confirmReset')" width="230" @confirm="resetCondition">
        <template #reference>
          <el-button type="warning">{{ t('conditionTree.resetCondition') }} </el-button>
        </template>
      </el-popconfirm>
    </template>
  </el-drawer>
</template>

<script setup lang="ts">
import { Filter, Plus } from '@element-plus/icons-vue'
import { useI18n } from 'vue-i18n'
import {
  ComparisonOperator,
  ConditionExpressionGroup,
  ConditionExpressionType,
  ConditionItem,
  ConditionSchema,
  LogicalOperator
} from '@/components/ConditionTree/type'
import ConditionGroup from '@/components/ConditionTree/ConditionGroup.vue'
import { conditionKey } from '@/components/ConditionTree/injectKey'
import { PropType, UnwrapRef } from 'vue'
import { debounce } from 'lodash-es'
import { useAppStore } from '@/store/modules/app'

defineOptions({ name: 'ConditionTree' })

const appStore = useAppStore()
// 是否是移动端
const mobile = computed(() => appStore.getMobile)

// 定义 props
const props = defineProps({
  id: {
    type: String,
    required: true
  },
  schemata: {
    type: Array as PropType<ConditionSchema[]>,
    required: true
  }
})

const { t } = useI18n()

const message = useMessage()

const drawer = ref(false)

const conditionRef = ref<InstanceType<typeof ConditionGroup>>()

// 尝试从localStorage获取条件 没有的时候再赋初始值
const conditionFromLocalStorage = localStorage.getItem(`condition-tree:${props.id}`)
const condition = ref<ConditionExpressionGroup>(
  conditionFromLocalStorage
    ? JSON.parse(conditionFromLocalStorage)
    : {
        '@type': 'cn.cas.imr.postgraduate.framework.common.pojo.advanced.ConditionExpressionGroup',
        id: 'root',
        logical: LogicalOperator.And,
        conditions: []
      }
)

provide<
  Ref<
    UnwrapRef<ConditionExpressionGroup>,
    UnwrapRef<ConditionExpressionGroup> | ConditionExpressionGroup
  >
>(conditionKey, condition)

const saveCondition = debounce(() => {
  // 将条件保存到localStorage
  localStorage.setItem(`condition-tree:${props.id}`, JSON.stringify(condition.value))
}, 500)

watch(
  () => condition.value,
  () => saveCondition(),
  { deep: true }
)

const addNewCondition = () => {
  conditionRef.value?.addNewCondition()
}

const open = () => {
  drawer.value = true
}

const close = () => {
  drawer.value = false
}

// 构建SQL
const buildSql = () => {
  // 解析条件
  const parseCondition = (condition) => {
    if (!condition.field) {
      throw new Error('field is required')
    }
    if (condition.type === ConditionExpressionType.Unary) {
      return `${condition.field} ${condition.operator}`
    }
    if ([ComparisonOperator.Like, ComparisonOperator.NotLike].includes(condition.operator)) {
      return `${condition.field} ${condition.operator} '%${condition.value}%'`
    } else {
      return `${condition.field} ${condition.operator} '${condition.value}'`
    }
  }

  // 递归解析组
  const parseGroup = (group: ConditionExpressionGroup) => {
    const conditions = group.conditions.map((cond: ConditionItem) => {
      if ('logical' in cond) {
        return `(${parseGroup(cond)})`
      }
      return parseCondition(cond)
    })
    return conditions.join(` ${group.logical} `)
  }

  return parseGroup(condition.value)
}

const advanced = ref(false)

const emits = defineEmits<(e: 'search', value?: string) => void>()

// 高级搜索
const advanceSearch = () => {
  // 调用函数
  try {
    const sqlWhere = buildSql()
    console.log('debug sql: ', sqlWhere)
    const json = encodeURIComponent(JSON.stringify(condition.value))
    const base64 = btoa(json)
    emits('search', base64)
    advanced.value = true
    close()
  } catch (e) {
    message.error(t('conditionTree.buildSqlError'))
  }
}

// 取消高级搜索
const resetAdvance = () => {
  advanced.value = false
  emits('search', undefined)
}

const resetCondition = () => {
  condition.value = {
    '@type': 'cn.cas.imr.postgraduate.framework.common.pojo.advanced.ConditionExpressionGroup',
    id: 'root',
    logical: LogicalOperator.And,
    conditions: []
  }
  localStorage.removeItem(`condition-tree:${props.id}`)
  close()
  resetAdvance()
}
</script>

<style scoped lang="scss"></style>
